:: ------------------------------------------------------------
:: Copyright (c) Microsoft Corporation.  All rights reserved.
:: Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
:: ------------------------------------------------------------

@echo off
setlocal EnableDelayedExpansion

:: ===========================================================================
:: Set up directory paths, logs for failed and disabled tests, etc
::
set CurDir=%~dp0

set argument=%*

:: Ensure we are running from RunTests
:: We cannot run it from Git source path since the corext environment
:: doesn't provide  build type (debug/retail) info in its environment.
:: So, we aren't sure if we need to go to debug-amd64\bin\RunTests or retail-amd64\bin\RunTests
:: So, executing from the destination directory itself.
echo %CurDir% >%temp%\runtests.curdir.txt
find /I "RunTests" %temp%\runtests.curdir.txt >nul
set ev=%errorlevel%
del %temp%\runtests.curdir.txt
if %ev% equ 1 goto RunFromRunTestsDirMsg

set CurDir=%~dp0
:: Remove the last backslash
set CurDir=%CurDir:~0,-1%

for %%d in (%CurDir%) do set ParentDir=%%~dpd

set _NTTREE=%ParentDir:~0,-1%%

set BINARIES_DIR=%_NTTREE%\FabricUnitTests
set DOTNETCLIDIR=%_NTTREE%\DotnetCoreCli

set path=%path%;%BINARIES_DIR%
set CheckGeneratedFilesReturn=true
set RunTestsReturn=true
set __OneBoxTestEnvironment__=true

set arg1=%1

if "!arg1!"=="/?" goto :PrintUsage
if "!arg1!"=="-?" goto :PrintUsage
if "!arg1!"=="/list" goto :ListTests

if "!arg1!"=="/skiprun" (

    call :CheckGeneratedFiles
    if "!CheckGeneratedFilesReturn!"=="false" exit /b 1

) else if "!arg1!"=="/skipcheck" (

    call :RunTests !argument:~11!
    if "!RunTestsReturn!"=="false" exit /b 1

) else (

    call :CheckGeneratedFiles
    if "!CheckGeneratedFilesReturn!"=="false" exit /b 1

    call :RunTests !argument!
    if "!RunTestsReturn!"=="false" exit /b 1
)

endlocal
goto :EOF

:: ===========================================================================
:: Checks autogenerated files
::
:CheckGeneratedFiles
set RETAIL_DIR=%_NTTREE%
set MANIFEST_FILE_DIFF=%BINARIES_DIR%\ManifestFileDiff.txt
set TRACING_CODE_FILE_DIFF=%BINARIES_DIR%\TracingCodeFileDiff.txt
set GENERATED_DIR=%SrcRoot%\prod\test\generated
set COUNTER_MANIFEST_FILE_DIFF=%BINARIES_DIR%\CounterManifestFileDiff.txt

set CheckTraceManifestFileReturn=true
set CheckIdlGeneratedHeaderFileReturn=true
set CheckForDriverSigningReturn=true
set CheckCounterManifestFileReturn=true

call :CheckTraceManifestFile
if "!CheckTraceManifestFileReturn!"=="false" (
    set CheckGeneratedFilesReturn=false
    goto :EOF
)

call :CheckIdlGeneratedHeaderFile
if "!CheckIdlGeneratedHeaderFileReturn!"=="false" (
    set CheckGeneratedFilesReturn=false
    goto :EOF
)

call :CheckForDriverSigning
if "!CheckForDriverSigningReturn!"=="false" (
    set CheckGeneratedFilesReturn=false
    goto :EOF
)

call :CheckCounterManifestFile
if "!CheckCounterManifestFileReturn!"=="false" (
    set CheckGeneratedFilesReturn=false
    goto :EOF
)

goto :EOF

:: ===========================================================================

:: Check Trace Manifest File
:CheckTraceManifestFile
echo.
set CHECKEDIN_MANIFEST_FILE=%SrcRoot%\prod\manifests\components\Microsoft-ServiceFabric-Events.man
set WINFAB_MANIFEST_FILE=%RETAIL_DIR%\Microsoft-ServiceFabric-Events.man

echo Checking if trace manifest file %WINFAB_MANIFEST_FILE% is up-to-date...

:: In SD/razzle environment, this script (and the tools  it invokes) was in the PATH environment
:: variable and was found under razzle tools depot. However, in Git, it doesn't exist any more.
:: To mitigate this, we have used a Nuget package that contains these tools and added a razzle_tools
:: environment variable to corext.config. We add this environment variable to PATH temporarily
:: and then revert the PATH to its original value.
set OriginalPath=%PATH%
set PATH=%PATH%;%RAZZLE_TOOLS%;%RAZZLE_TOOLS%\x86

%RETAIL_DIR%\ManifestGeneratorManaged.exe %WINFAB_MANIFEST_FILE%

set ev=%ERRORLEVEL%
set PATH=%OriginalPath%

if %ev% equ 1 (
  echo.
  echo FAILED. Trace manifest generation failed.
  echo.

  set CheckTraceManifestFileReturn=false
  goto :EOF
)

:: Comparing generated manifest file with checked in file %CHECKEDIN_MANIFEST_FILE%...

rep -find:"%_NTTREE%" -replace:"[_NTTREE]" %WINFAB_MANIFEST_FILE% > nul

fc %WINFAB_MANIFEST_FILE% %CHECKEDIN_MANIFEST_FILE% >> %MANIFEST_FILE_DIFF%

if ERRORLEVEL 1 (
  echo FAILED. Trace manifest check failed.
  echo Please run %BINARIES_DIR%/UpdateGeneratedFiles.cmd script to update manifest file.

  set CheckTraceManifestFileReturn=false
) else (
    echo SUCCESS. Trace manifest is up-to-date.
)

echo.

goto :EOF

:: ===========================================================================

:: Check Counter Manifest File
:CheckCounterManifestFile
echo.
set CHECKEDIN_COUNTER_MANIFEST_FILE=%SrcRoot%\prod\manifests\components\WFPerf.man
set WINFAB_COUNTER_NATIVE_MANIFEST_FILE=%RETAIL_DIR%\WFPerfNative.man
set WINFAB_COUNTER_SDK_MANIFEST_FILE=%RETAIL_DIR%\WFPerfSdk.man
set WINFAB_COUNTER_MANIFEST_FILE=%RETAIL_DIR%\WFPerf.man
set WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT=%RETAIL_DIR%\WFPerfDebugOutput.txt

echo Checking if counter manifest file %CHECKEDIN_COUNTER_MANIFEST_FILE% is up-to-date...

%RETAIL_DIR%\CounterManifestGeneratorManaged.exe %WINFAB_COUNTER_NATIVE_MANIFEST_FILE% %WINFAB_COUNTER_SDK_MANIFEST_FILE% > %WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT%

if %ERRORLEVEL% equ 0 (
  %RETAIL_DIR%\CounterManifestGeneratorManagedRuntime.exe %WINFAB_COUNTER_SDK_MANIFEST_FILE% %WINFAB_COUNTER_MANIFEST_FILE% > %WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT%
)

set ev=%ERRORLEVEL%

if %ev% neq 0 (
  echo.
  echo FAILED. Counter Manifest generation failed.
  echo Please check %WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT% file for errors.
  echo.

  set CheckCounterManifestFileReturn=false
  goto :EOF
)

:: Comparing generated counter manifest file with checked in file %CHECKEDIN_COUNTER_MANIFEST_FILE%...

fc %WINFAB_COUNTER_MANIFEST_FILE% %CHECKEDIN_COUNTER_MANIFEST_FILE% > %COUNTER_MANIFEST_FILE_DIFF%

if ERRORLEVEL 1 (
  echo FAILED. Counter Manifest check failed.
  echo Please run %BINARIES_DIR%/UpdateGeneratedFiles.cmd script to update manifest file.

  set CheckCounterManifestFileReturn=false
) else (
    echo SUCCESS. Counter manifest is up-to-date.
)

echo.

goto :EOF



:: ===========================================================================

:: Check Idl-Generated Header File
:CheckIdlGeneratedHeaderFile
echo.
set CHECKEDIN_FILE[1]=%SrcRoot%\prod\src\prebuilt\internal\FabricClient_.h
set GENERATED_FILE[1]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricClient_.h
set CHECKEDIN_FILE[2]=%SrcRoot%\prod\src\prebuilt\internal\FabricCommon_.h
set GENERATED_FILE[2]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricCommon_.h
set CHECKEDIN_FILE[3]=%SrcRoot%\prod\src\prebuilt\internal\FabricData_.h
set GENERATED_FILE[3]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricData_.h
set CHECKEDIN_FILE[4]=%SrcRoot%\prod\src\prebuilt\internal\FabricImageStore_.h
set GENERATED_FILE[4]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricImageStore_.h
set CHECKEDIN_FILE[5]=%SrcRoot%\prod\src\prebuilt\internal\FabricRuntime_.h
set GENERATED_FILE[5]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricRuntime_.h
set CHECKEDIN_FILE[6]=%SrcRoot%\prod\src\prebuilt\internal\FabricTypes_.h
set GENERATED_FILE[6]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricTypes_.h
set CHECKEDIN_FILE[7]=%SrcRoot%\prod\src\prebuilt\sdk\FabricClient.h
set GENERATED_FILE[7]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricClient.h
set CHECKEDIN_FILE[8]=%SrcRoot%\prod\src\prebuilt\sdk\FabricCommon.h
set GENERATED_FILE[8]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricCommon.h
set CHECKEDIN_FILE[9]=%SrcRoot%\prod\src\prebuilt\sdk\FabricRuntime.h
set GENERATED_FILE[9]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricRuntime.h
set CHECKEDIN_FILE[10]=%SrcRoot%\prod\src\prebuilt\sdk\FabricTypes.h
set GENERATED_FILE[10]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricTypes.h
set CHECKEDIN_FILE[11]=%SrcRoot%\prod\src\prebuilt\internal\FabricInfrastructureService_.h
set GENERATED_FILE[11]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricInfrastructureService_.h
set CHECKEDIN_FILE[12]=%SrcRoot%\prod\src\prebuilt\sdk\FabricTokenValidationService_.h
set GENERATED_FILE[12]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricTokenValidationService_.h
set CHECKEDIN_FILE[13]=%SrcRoot%\prod\src\prebuilt\internal\FabricServiceCommunication_.h
set GENERATED_FILE[13]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricServiceCommunication_.h
set CHECKEDIN_FILE[14]=%SrcRoot%\prod\src\prebuilt\internal\FabricTestabilityService_.h
set GENERATED_FILE[14]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricTestabilityService_.h

set CHECKEDIN_FILE[15]=%SrcRoot%\prod\src\prebuilt\internal\FabricClient__i.c
set GENERATED_FILE[15]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricClient__i.c
set CHECKEDIN_FILE[16]=%SrcRoot%\prod\src\prebuilt\internal\FabricCommon__i.c
set GENERATED_FILE[16]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricCommon__i.c
set CHECKEDIN_FILE[17]=%SrcRoot%\prod\src\prebuilt\internal\FabricData__i.c
set GENERATED_FILE[17]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricData__i.c
set CHECKEDIN_FILE[18]=%SrcRoot%\prod\src\prebuilt\internal\FabricImageStore__i.c
set GENERATED_FILE[18]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricImageStore__i.c
set CHECKEDIN_FILE[19]=%SrcRoot%\prod\src\prebuilt\internal\FabricInfrastructureService__i.c
set GENERATED_FILE[19]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricInfrastructureService__i.c
set CHECKEDIN_FILE[20]=%SrcRoot%\prod\src\prebuilt\internal\FabricReliableMessaging__i.c
set GENERATED_FILE[20]=%SrcRoot%\prod\src\idl\internal\objd\FabricReliableMessaging__i.c
set CHECKEDIN_FILE[21]=%SrcRoot%\prod\src\prebuilt\internal\FabricRuntime__i.c
set GENERATED_FILE[21]=%SrcRoot%\prod\src\idl\internal\objd\FabricRuntime__i.c
set CHECKEDIN_FILE[22]=%SrcRoot%\prod\src\prebuilt\internal\FabricServiceCommunication__i.c
set GENERATED_FILE[22]=%SrcRoot%\prod\src\idl\internal\objd\FabricServiceCommunication__i.c
set CHECKEDIN_FILE[23]=%SrcRoot%\prod\src\prebuilt\internal\FabricTokenValidationService__i.c
set GENERATED_FILE[23]=%SrcRoot%\prod\src\idl\internal\objd\FabricTokenValidationService__i.c
set CHECKEDIN_FILE[24]=%SrcRoot%\prod\src\prebuilt\internal\KPhysicalLog__i.c
set GENERATED_FILE[24]=%SrcRoot%\prod\src\idl\internal\objd\KPhysicalLog__i.c
set CHECKEDIN_FILE[25]=%SrcRoot%\prod\src\prebuilt\sdk\FabricClient_i.c
set GENERATED_FILE[25]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricClient_i.c
set CHECKEDIN_FILE[26]=%SrcRoot%\prod\src\prebuilt\sdk\FabricCommon_i.c
set GENERATED_FILE[26]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricCommon_i.c
set CHECKEDIN_FILE[27]=%SrcRoot%\prod\src\prebuilt\sdk\FabricRuntime_i.c
set GENERATED_FILE[27]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricRuntime_i.c

set CHECKEDIN_FILE[28]=%SrcRoot%\prod\src\prebuilt\internal\FabricFaultAnalysisService_.h
set GENERATED_FILE[28]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricFaultAnalysisService_.h
set CHECKEDIN_FILE[29]=%SrcRoot%\prod\src\prebuilt\internal\FabricFaultAnalysisService__i.c
set GENERATED_FILE[29]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricFaultAnalysisService__i.c

set CHECKEDIN_FILE[30]=%SrcRoot%\prod\src\prebuilt\internal\FabricUpgradeOrchestrationService_.h
set GENERATED_FILE[30]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricUpgradeOrchestrationService_.h

set CHECKEDIN_FILE[31]=%SrcRoot%\prod\src\prebuilt\internal\SfStatus.h
set GENERATED_FILE[31]=%SrcRoot%\prod\src\Reliability\data\statuscodes\lib\objd\amd64\SfStatus.h

echo Checking if Idl-generated Header File for Linux is up-to-date...

set IDL_GEN_HEADER_FILE_DIFF=%BINARIES_DIR%\IdlGenHeaderFileDiff.txt
for %%x in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31) do (
	if exist !GENERATED_FILE[%%x]! (
        fc !CHECKEDIN_FILE[%%x]! !GENERATED_FILE[%%x]! >> %IDL_GEN_HEADER_FILE_DIFF%
        if ERRORLEVEL 1 (
            set CheckIdlGeneratedHeaderFileReturn=false
        )
    )
)

if "!CheckIdlGeneratedHeaderFileReturn!"=="false" (
    echo FAILED. Idl generated header files check failed.
    echo Please run %BINARIES_DIR%/UpdateGeneratedFiles.cmd script to update header files.
) else (
    echo SUCCESS. Idl generated header files are all up-to-date.
)
echo.

goto :EOF

:: ===========================================================================

:: Check For Driver Signing
:CheckForDriverSigning

echo Checking if a new signed driver is needed...

:: If the header files are opened (i.e. modified), then it means that a new signed driver is needed
::
:: The files use forward slash since git status reports them with a /
:: Also, not using the full path since Git reports a relative path which
:: we are using to findstr
set LEASE_HEADER_1=/src/prod/src/lease/inc/public/leaselayerpublic.h
set LEASE_HEADER_2=/src/prod/src/lease/inc/public/LeaseListenEndPoint.h
set LEASE_HEADER_3=/src/prod/src/lease/inc/private/leaselayerio.h

@git status 2> nul | FINDSTR /I /C:"%LEASE_HEADER_1%"
if %ERRORLEVEL% neq 1 goto :DriverSigningFailed
@git status 2> nul | FINDSTR /I /C:"%LEASE_HEADER_2%"
if %ERRORLEVEL% neq 1 goto :DriverSigningFailed
@git status 2> nul | FINDSTR /I /C:"%LEASE_HEADER_3%"
if %ERRORLEVEL% neq 1 goto :DriverSigningFailed

echo SUCCESS. New signed driver not needed.
echo.

goto :EOF

:DriverSigningFailed
echo FAILED. Check for driver signing failed, a new signed driver is needed.
echo.

set CheckForDriverSigningReturn=false

goto :EOF

:: ===========================================================================
:: Run Tests

:RunTests
set runtestsargs=%*

set FabricConfigFileName=
set FabricPackageFileName=
set FabricDataRoot=
set FabricBinRoot=
set FabricCodePath=
set FabricRoot=
pushd %BINARIES_DIR%

echo Stopping trace sessions...
logman stop winfab -ets > nul
logman stop lease -ets > nul
logman stop ktl -ets > nul

logman stop FabricAppInfoTraces > nul
logman stop FabricLeaseLayerTraces > nul
logman stop FabricSFBDMiniportTraces > nul
logman stop FabricQueryTraces > nul
logman stop FabricTraces > nul
echo Trace sessions stopped.

set runtestsarg1=%1

echo.
echo Invoking RunTests...

cd %CurDir%
if "!runtestsarg1!"=="/ese" (

    set Cmd=%DOTNETCLIDIR%\dotnet.exe %CurDir%\RunTests.dll !runtestsargs:~5! /overrideparams:EseStoreEnabled=true

) else if "!runtestsarg1!"=="/nativestore" (

    set Cmd=%DOTNETCLIDIR%\dotnet.exe %CurDir%\RunTests.dll !runtestsargs:~13! /overrideparams:NativeStoreEnabled=true

) else (

    set Cmd=%DOTNETCLIDIR%\dotnet.exe %CurDir%\RunTests.dll !runtestsargs!
)

echo %Cmd%
%Cmd%

if ERRORLEVEL 1 (
  echo FAILED. RunTests failed
  set RunTestsReturn=false
)

popd
goto :EOF
REM IF [%*] == [] (
REM echo "No Args specified.Running CITs locally"
REM )

:: ===========================================================================
:: List the tests
::
:ListTests

%DOTNETCLIDIR%\dotnet.exe %CurDir%\RunTests.dll %*

endlocal
goto :EOF

:: ===========================================================================
:: Print the usage
::

:PrintUsage

echo.
echo This script runs all checkin and Xml Tests through RunTests
echo.
echo Usage: RunTests.cmd [/skiprun] [/skipcheck] [/ese] [/nativestore] [Arguments for RunTests]
echo.
echo where,
echo.
echo    /skiprun                    Skips the run, just check autogenerated files. This should always be the first argument passed in.
echo.
echo    /skipcheck                  Skips the check for autogenerated file, just runs the tests. This should always be the first argument passed in.
echo.
echo    /ese                        Uses Ese as system services and KVS store for all tests run (unless test overrides). This should always be the first argument passed in unless skiprun/skipcheck is first argument then it should be second.
echo.
echo    /nativestore                Uses Native Store as system services and KVS store for all tests run (unless test overrides). This should always be the first argument passed in unless skiprun/skipcheck is first argument then it should be second.
echo.
echo  ADDITIONAL Arguments for RunTests are below:
echo.


%DOTNETCLIDIR%\dotnet.exe %CurDir%\RunTests.dll /?
goto :EOF

:: ===========================================================================
:: Displays a message to run the unit tests from RunTests folder
::
:RunFromRunTestsDirMsg
echo.
echo Please run this script from RunTests folder under bin
echo E.g. from \rdnext\WindowsFabric\out\debug-amd64\bin\RunTests
echo.
echo For detailed usage, please type '%~nx0 /?'
echo.

endlocal
goto :EOF
